<?php

namespace app\model;

use think\facade\Db;

class BatchUpdate
{
    /**
     * 批量更新数据（支持JSON字段）
     * @param string $table 表名
     * @param array $data 更新数据数组
     * @param string $primaryKey 主键字段名，默认'id'
     * @return int 影响的行数
     * @throws \Exception
     */
    public static function update(string $table, array $data, string $primaryKey = 'id'): int
    {
        if (empty($data)) {
            return 0;
        }

        try {
            // 构建批量更新SQL
            $sql = self::buildBatchUpdateSql($table, $data, $primaryKey);

            // 执行更新
            return Db::execute($sql);

        } catch (\Exception $e) {
            throw new \Exception("批量更新失败: " . $e->getMessage());
        }
    }

    /**
     * 构建批量更新SQL语句
     */
    private static function buildBatchUpdateSql(string $table, array $data, string $primaryKey): string
    {
        // 获取所有字段（排除主键）
        $fields = array_keys($data[0]);
        $fields = array_filter($fields, function($field) use ($primaryKey) {
            return $field !== $primaryKey;
        });

        // 构建CASE WHEN语句
        $cases = [];
        $ids = [];

        foreach ($fields as $field) {
            $caseSql = "`{$field}` = CASE `{$primaryKey}` ";

            foreach ($data as $item) {
                $id = $item[$primaryKey];
                $value = $item[$field] ?? null;

                // 处理JSON字段
                if (self::isJsonField($value) || is_array($value) || is_object($value)) {
                    $value = self::formatJsonValue($value);
                } else {
                    $value = self::escapeValue($value);
                }

                $caseSql .= "WHEN {$id} THEN {$value} ";
                $ids[$id] = true;
            }

            $caseSql .= "ELSE `{$field}` END";
            $cases[] = $caseSql;
        }

        // 构建完整SQL
        $idList = implode(',', array_keys($ids));
        $setClause = implode(', ', $cases);

        return "UPDATE `{$table}` SET {$setClause} WHERE `{$primaryKey}` IN ({$idList})";
    }

    /**
     * 判断是否为JSON字段值
     */
    private static function isJsonField($value): bool
    {
        if (is_array($value) || is_object($value)) {
            return true;
        }

        if (is_string($value)) {
            // 尝试解码，如果是有效的JSON字符串
            json_decode($value);
            return json_last_error() === JSON_ERROR_NONE;
        }

        return false;
    }

    /**
     * 格式化JSON值
     */
    private static function formatJsonValue($value): string
    {
        if (is_array($value) || is_object($value)) {
            $value = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        }

        // 转义特殊字符并添加引号
        return "'" . addslashes($value) . "'";
    }

    /**
     * 转义普通值
     */
    private static function escapeValue($value): string
    {
        if (is_null($value)) {
            return 'NULL';
        }

        if (is_bool($value)) {
            return $value ? '1' : '0';
        }

        if (is_numeric($value)) {
            return $value;
        }

        return "'" . addslashes($value) . "'";
    }
}
